package files;

import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Map.Entry;
import java.util.TreeMap;

import polarity.Polarity;

import classifier.Classifier;
import classifier.ClassifierManager;

import tools.Writer;

public class TweetManager {

	static int count = 0;
	
	private static ArrayList<Tweet> alTweetTest = new ArrayList<Tweet>();
	private static ArrayList<Tweet> alTweetTrain = new ArrayList<Tweet>();
	private static ArrayList<Tweet> alTweetResultat = new ArrayList<Tweet>();
	
	public static ArrayList<Tweet> getAlTweetTest() {return alTweetTest; }
	public static ArrayList<Tweet> getAlTweetTrain() {return alTweetTrain; }
	
	private static String method = "multinomial"; // valeur par defaut
	
        /**
         * Modifie la methode de calcul
         * @param method methode a utiliser au choix: "multinomial" ou "binomial"
         */
	private static void setMethod(String method) { TweetManager.method = method; }
	public static String getMethod() { return method; }
	
        /**
         * constructeur
         */
	private TweetManager() { }
	
        /**
         * Ajoute un tweet a tester
         * @param tweetTest tweet a tester
         */
	public static void addTweetTest(Tweet tweetTest)
	{
		alTweetTest.add(tweetTest);
		
		ClassifierManager.setTweetTestClassifier(tweetTest);
		
		tweetTest.useMethod();
		count++;
	}
	
        /**
         * Ajoute un tweet de resultat
         * @param tweetResultat tweet de resultat
         */
	public static void addTweetResultat(Tweet tweetResultat) 
	{
		alTweetResultat.add(tweetResultat);
	}
	
        /**
         * Ajoute un tweet d'entrainement
         * @param tweetResultat tweet d'entrainement
         */
	public static void addTweetTrain(Tweet tweetTrain)
	{
		alTweetTrain.add(tweetTrain);
	}
	
	/*
	public static void calculateBayesMultinomial()
	{
		for(int i=0; i<alTweetTrain.size();i++)
		{
			alTweetTrain.get(i).calculateBayesMultinomial();
		}
	}
	*/
	
        /**
         * Finalise la lecture du resultat
         */
	public static void readingResultatFinish() 
	{
		int nbrTweet = alTweetTest.size();
		int nbrTweetReussi = 0;
		
		for(int i=0;i<alTweetTest.size();i++)
		{
			if ( ClassifierManager.getSepareMarkOn() == false  ) alTweetResultat.get(i).setMark("general");
			
			//System.out.println("Ligne "+i+" : "+alTweetTest.get(i).getType()+" - "+alTweetResultat.get(i).getType()+" Bayes : "+(alTweetTest.get(i).getBayesMultinomialHt()).get("positive")+" "+(alTweetTest.get(i).getBayesMultinomialHt()).get("negative")
				//	+" "+(alTweetTest.get(i).getBayesMultinomialHt()).get("neutral")+" "+(alTweetTest.get(i).getBayesMultinomialHt()).get("irrelevant"));
			
			//System.out.println("Ligne "+i+" : "+alTweetTest.get(i).getType()+" - "+alTweetResultat.get(i).getType());
			if ( alTweetTest.get(i).getType().equals(alTweetResultat.get(i).getType()) )
			{
				nbrTweetReussi++;
			}
			else System.out.println("Ligne "+i+" : "+alTweetTest.get(i).getType()+" - "+alTweetResultat.get(i).getType());
		}
	
		printMatrix();
		
		System.out.println("nbrTweet : "+nbrTweet);
		System.out.println("nbrTweetReussi : "+nbrTweetReussi);
		System.out.println("Pourcentage : "+nbrTweetReussi*100/nbrTweet);
		
		
	}
	
        /**
         * Finalise la lecture des tests
         */
	public static void readingTestFinish() 
	{
		String string = "";
		for(int i=0;i<alTweetTest.size();i++)
		{
			Tweet tweet = alTweetTest.get(i);
			//string += "("+tweet.getType()+","+tweet.getMark()+") "+tweet.getContent()+"\n";
			string += tweet.getType()+"\n";
		}
		Writer.writeResult("resultat.txt", string);
		
	}
	
        /**
         * Affiche le resultat de la matrice et calcule les scores
         */
	public static void printMatrix()
	{
		
		Hashtable<String, Hashtable<String, Integer>> matrixHt = new Hashtable<String, Hashtable<String, Integer>>();
		
		Hashtable<String, Integer> pos =  new Hashtable<String,Integer>(); 
		pos.put("positive", 0); matrixHt.put("positive", pos);
		pos.put("negative", 0); matrixHt.put("positive", pos);
		pos.put("neutral", 0); matrixHt.put("positive", pos);
		pos.put("irrelevant", 0); matrixHt.put("positive", pos);
		
		Hashtable<String, Integer> neg =  new Hashtable<String,Integer>(); 
		neg.put("positive", 0); matrixHt.put("negative", neg);
		neg.put("negative", 0); matrixHt.put("negative", neg);
		neg.put("neutral", 0); matrixHt.put("negative", neg);
		neg.put("irrelevant", 0); matrixHt.put("negative", neg);
		
		Hashtable<String, Integer> neu =  new Hashtable<String,Integer>(); 
		neu.put("positive", 0); matrixHt.put("neutral", neu);
		neu.put("negative", 0); matrixHt.put("neutral", neu);
		neu.put("neutral", 0); matrixHt.put("neutral", neu);
		neu.put("irrelevant", 0); matrixHt.put("neutral", neu);
		
		Hashtable<String, Integer> irr =  new Hashtable<String,Integer>(); 
		irr.put("positive", 0); matrixHt.put("irrelevant", irr);
		irr.put("negative", 0); matrixHt.put("irrelevant", irr);
		irr.put("neutral", 0); matrixHt.put("irrelevant", irr);
		irr.put("irrelevant", 0); matrixHt.put("irrelevant", irr);
		
	
		
		for(int i=0;i<alTweetTest.size();i++)
		{
			if ( alTweetTest.get(i).getType().equals(alTweetResultat.get(i).getType()) == false)
			{
				
				int value = matrixHt.get(alTweetTest.get(i).getType()).get(alTweetResultat.get(i).getType());
				//matrixHt.get(alTweetTest.get(i).getType()).put(alTweetResultat.get(i).getType(), 10);
				matrixHt.get(alTweetTest.get(i).getType()).put(alTweetResultat.get(i).getType(), value+1);
				
			}
		}
	
		System.out.print("\t \t \t " );
		System.out.print("PositivePredit \t ");
		System.out.print("NegativePredit \t " );
		System.out.print("NeutralPredit \t " );
		System.out.print("IrrelevantPredit \t " );
		System.out.println();
		
		System.out.print("PositiveAPredire \t\t");System.out.print(matrixHt.get("positive").get("positive")+"\t\t\t");System.out.print(matrixHt.get("negative").get("positive")+"\t\t\t");System.out.print(matrixHt.get("neutral").get("positive")+"\t\t");System.out.print(matrixHt.get("irrelevant").get("positive")+"\n");
		System.out.print("NegativeAPredire \t\t");System.out.print(matrixHt.get("positive").get("negative")+"\t\t\t");System.out.print(matrixHt.get("negative").get("negative")+"\t\t\t");System.out.print(matrixHt.get("neutral").get("negative")+"\t\t");System.out.print(matrixHt.get("irrelevant").get("negative")+"\n");
		System.out.print("NeutralAPredire \t\t");System.out.print(matrixHt.get("positive").get("neutral")+"\t\t\t");System.out.print(matrixHt.get("negative").get("neutral")+"\t\t\t");System.out.print(matrixHt.get("neutral").get("neutral")+"\t\t");System.out.print(matrixHt.get("irrelevant").get("neutral")+"\n");
		System.out.print("IrrelevantAPredire \t\t");System.out.print(matrixHt.get("positive").get("irrelevant")+"\t\t\t");System.out.print(matrixHt.get("negative").get("irrelevant")+"\t\t\t");System.out.print(matrixHt.get("neutral").get("irrelevant")+"\t\t");System.out.print(matrixHt.get("irrelevant").get("irrelevant")+"\n");
	
		int score = 0;
		score+=  matrixHt.get("positive").get("positive")*0 + matrixHt.get("negative").get("positive")*2 +matrixHt.get("neutral").get("positive")*3 +matrixHt.get("irrelevant").get("positive")*4 ;
		score+=  matrixHt.get("positive").get("negative")*2 + matrixHt.get("negative").get("negative")*0 +matrixHt.get("neutral").get("negative")*3 +matrixHt.get("irrelevant").get("negative")*3 ;
		score+=  matrixHt.get("positive").get("neutral")*4 + matrixHt.get("negative").get("neutral")*4 +matrixHt.get("neutral").get("neutral")*0 +matrixHt.get("irrelevant").get("neutral")*1 ;
		score+=  matrixHt.get("positive").get("irrelevant")*4 + matrixHt.get("negative").get("irrelevant")*4 +matrixHt.get("neutral").get("irrelevant")*1 +matrixHt.get("irrelevant").get("irrelevant")*0 ;
		
		System.out.println("SCORE : "+score);
	
	}
	
	/**
         * Lance la methode d'entrainement
         */
	public static void trainingMethod()
	{
		switch( method)
		{
			case "binomial": trainingMethodBinomial(); break;
			case "multinomial": trainingMethodMultinomial(); break;
			case "cluster": trainingMethodCluster();  break;
			case "moyenne": trainingMethodAverage(); break;
			default: break; 
		}	
	}
	
        /**
         * Entrainement binomial
         */
	private static void trainingMethodBinomial()
	{
		TreeMap<String, Integer> vocabularyAll = ClassifierManager.getClassifierHt().get("general").getVocabularyGeneral();
		// Pour chaque mots
		for(Entry<String, Integer> entryVocabulary : vocabularyAll.entrySet() )
		{
			Hashtable<String, Classifier> classifierHt = ClassifierManager.getClassifierHt();
			// Pour chaque Classifieur
			for(Entry<String, Classifier> entryClassifier : classifierHt.entrySet() )
			{
				Hashtable<String, Polarity> polarityHt = entryClassifier.getValue().getPolarityManager().getPolarityHt();
				// Pour chaque Polarite
				for(Entry<String, Polarity> entryPolarity : polarityHt.entrySet() )
				{
					TreeMap<String, Integer> vocabulary = entryPolarity.getValue().getVocabulary();
					TreeMap<String, Double> bayes = entryPolarity.getValue().getBayesBinomial();
					
					
					
					Double value;
					if ( vocabulary.containsKey(entryVocabulary.getKey()))
					{
						// Occurence du mot dans la polarite / Nombre de mots de la polarite
						value =  (double) ((double)vocabulary.get(entryVocabulary.getKey())/(double)entryPolarity.getValue().getNumberOfWords());
						bayes.put(entryVocabulary.getKey(), value);
					}
					else
					{
						value =  0.0;
						bayes.put(entryVocabulary.getKey(), value);
						
					}
					
				}
			}
		}
	}
	
        /**
         * Entrainement multinomial
         */
	private static void trainingMethodMultinomial() 
	{
		
		/*** Verison 1 ***/
//		ClassifierManager.getClassifierGeneral();
//		TreeMap<String, Integer> vocabularyAll = ClassifierManager.getClassifierGeneral().getVocabularyGeneral();
//		for(Entry<String, Integer> set : vocabularyAll.entrySet() )
//		{
//			ArrayList<Classifier> alClassifier =  ClassifierManager.getClassifierAl();
//			for(int i=0;i<alClassifier.size();i++)
//			{
//				Classifier classifierTmp = alClassifier.get(i);
//				ArrayList<TreeMap<String, Integer>> alVocabulary = classifierTmp.getVocabularyWordCountAl();
//				ArrayList<TreeMap<String, Float>> alBayes = classifierTmp.getBayesAl();
//				for(int j=0;j<alVocabulary.size();j++)
//				{
//					TreeMap<String, Integer> vocabularyTmp = alVocabulary.get(j);
//					TreeMap<String, Float> bayesTmp = alBayes.get(j);
//					if ( vocabularyTmp.containsKey(set.getKey()))
//					{
//						float value = (float) ((vocabularyTmp.get(set.getKey())+1.00)/(classifierTmp.getNumberOfWords()+classifierTmp.getNumberOfDifferentWords()));
//						bayesTmp.put(set.getKey(), value);
//					}
//					else
//					{
//						float value = (float)(1.00)/(classifierTmp.getNumberOfWords()+classifierTmp.getNumberOfDifferentWords());
//						bayesTmp.put(set.getKey(), value);
//					}
//				}
//				 
//				
//				 // Nombre de fois que le mots apparait ds la classe
//				 // Nombre de mots ds le voc
//				 // Nombre de mots differents
//				 
//			 }
//			
//		}
		/*** Version 2 ***/
		TreeMap<String, Integer> vocabularyAll = ClassifierManager.getClassifierHt().get("general").getVocabularyGeneral();
		// Pour chaque mots
		for(Entry<String, Integer> entryVocabulary : vocabularyAll.entrySet() )
		{
			Hashtable<String, Classifier> classifierHt = ClassifierManager.getClassifierHt();
			// Pour chaque Classifieur
			for(Entry<String, Classifier> entryClassifier : classifierHt.entrySet() )
			{
				Hashtable<String, Polarity> polarityHt = entryClassifier.getValue().getPolarityManager().getPolarityHt();
				// Pour chaque Polarite
				for(Entry<String, Polarity> entryPolarity : polarityHt.entrySet() )
				{
					TreeMap<String, Integer> vocabulary = entryPolarity.getValue().getVocabulary();
					TreeMap<String, Double> bayes = entryPolarity.getValue().getBayesMultinomial();
					
					
					
					
					Double value;
					if ( vocabulary.containsKey(entryVocabulary.getKey()))
					{
						value =  (Double) ((vocabulary.get(entryVocabulary.getKey())+1.00)/(entryPolarity.getValue().getNumberOfWords()+ entryClassifier.getValue().getPolarityManager().getNumberOfDifferentWords()));
						bayes.put(entryVocabulary.getKey(), value);
						//float value = (double) ((vocabulary.get(entryVocabulary.getKey())+1.00)/(entryPolarity.getValue().getNumberOfWords()+ entryClassifier.getValue().getPolarityManager().getNumberOfDifferentWords()));
//						if ( entryVocabulary.getKey().compareTo("tokyo") == 0 && entryPolarity.getKey().compareTo("positive") == 0)
//						{
//							System.out.println("Lucie w"+entryVocabulary.getKey()+" polarite "+entryPolarity.getKey()+" value "+test+ " marque "+entryClassifier.getKey());
//							System.out.println("Thomas " +entryClassifier.getValue().getPolarityManager().getNumberOfDifferentWords());
//						}
					}
					else
					{
						value =  (Double) ((1.00)/(entryPolarity.getValue().getNumberOfWords()+ entryClassifier.getValue().getPolarityManager().getNumberOfDifferentWords()));
						//double value = 1.00/(double)(entryPolarity.getValue().getNumberOfWords()+ entryClassifier.getValue().getPolarityManager().getNumberOfDifferentWords());
						bayes.put(entryVocabulary.getKey(), value);
//						if ( entryVocabulary.getKey().compareTo("macao") == 0 && entryClassifier.getKey().compareTo("apple") == 0)
//						{
//							System.out.println("Lucie w"+entryVocabulary.getKey()+" polarite "+entryPolarity.getKey()+" value "+test+ " marque "+entryClassifier.getKey());
//							System.out.println("Thomas " +entryPolarity.getValue().getNumberOfWords());
//						}
						
					}
					
					/*
					if ( entryClassifier.getKey() == "microsoft" && entryPolarity.getKey() == "positive") 
					{
						System.out.println("Classifier "+entryClassifier.getKey());
						System.out.println("Polarite "+entryPolarity.getKey());
						System.out.println("Mot "+entryVocabulary.getKey());
						System.out.println(entryClassifier.getValue().getPolarityManager().getNumberOfDifferentWords());
						System.out.println("Value "+value);
					}
					*/
					
				}
			}
		}
	}
	
        /**
         * Entrainement avec la methode du cluster
         */
	private static void trainingMethodCluster()
	{
		TreeMap<String, Integer> vocabularyAll = ClassifierManager.getClassifierHt().get("general").getVocabularyGeneral();
		
		for(Entry<String, Integer> entryVocabulary : vocabularyAll.entrySet() )
		{
			for(int i=0;i<alTweetTrain.size();i++)
			{
				Tweet tweet = alTweetTrain.get(i);
				//for(int j=)
			}
		}
		
	}
	/**
         * Entrainement avec la methode de la moyenne
         */
	private static void trainingMethodAverage()
	{
		
	}
	
}
